/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.celiosilva.simbanc.business;

import com.celiosilva.simbanc.beans.Cliente;
import com.celiosilva.simbanc.beans.ClienteFisico;
import com.celiosilva.simbanc.beans.ClienteJuridico;
import com.celiosilva.simbanc.beans.enums.EstadoCliente;
import com.celiosilva.simbanc.business.util.Sucesso;
import com.celiosilva.simbanc.exceptions.RegraNegocioException;
import com.celiosilva.simbanc.exceptions.SimbancException;
import com.celiosilva.simbanc.util.Validador;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;

/**
 *
 * @author celio@celiosilva.com
 */
public class ClienteBusiness {

    private final                   Map<Integer,Cliente>        clientes        = new HashMap<Integer, Cliente>();

    private static final            Logger                      log             = Logger.getLogger(ClienteBusiness.class);
    private static final            ClienteBusiness             instance        = new ClienteBusiness();
    private ClienteBusiness() {}
    public static final ClienteBusiness getInstance() {
        return instance;
    }

    public Sucesso cadastrarCliente(Cliente cliente) throws SimbancException {
        if (cliente.getEmail() != null && cliente.getEmail().length() > 0)
            Validador.validarFormatoEMail(cliente.getEmail());
        cliente.setCodigo(clientes.size() + 1);
        cliente.setEstadoCliente(EstadoCliente.ATIVO);
        this.clientes.put(cliente.getCodigo(), cliente);
        return new Sucesso(String.format("Cliente %s cadastrado com sucesso!", cliente.getNomeCompleto()));
    }

    public Cliente consultarClientePorCodigo(Integer codCliente){
        return this.clientes.get(codCliente);
    }

    public Sucesso alterarCliente(Cliente cliente) throws SimbancException{
        Cliente consultado = this.clientes.get(cliente.getCodigo());
        if (consultado.getEstadoCliente() != EstadoCliente.ATIVO){
            String mensagem = String.format("Cliente %s está %s e não pode ser alterado.",
                                            consultado.getNomeCompleto(),
                                            consultado.getEstadoCliente());
            throw new RegraNegocioException(mensagem);
        }
        if (cliente.getEmail() != null && cliente.getEmail().length() > 0)
            Validador.validarFormatoEMail(cliente.getEmail());
        this.clientes.put(cliente.getCodigo(), cliente);
        return new Sucesso(String.format("Cliente %s alterado com sucesso!", cliente.getNomeCompleto()));
    }

    public Sucesso alterarCliente(ClienteFisico cliente){
        this.clientes.put(cliente.getCodigo(), cliente);
        return new Sucesso(String.format("Cliente Físico %s alterado com sucesso!", cliente.getNomeCompleto()));
    }

    public Sucesso alterarCliente(ClienteJuridico cliente){
        this.clientes.put(cliente.getCodigo(), cliente);
        return new Sucesso(String.format("Cliente Jurídico %s alterado com sucesso!", cliente.getNomeCompleto()));
    }

    public Sucesso bloquearCliente(Cliente cliente){
        log.info("bloquear cliente usando objeto cliente:" + cliente);
        return this.bloquearCliente(cliente.getCodigo());
    }

    public Sucesso bloquearCliente(Integer codCliente){
        Cliente cliente = this.clientes.get(codCliente);
        cliente.setEstadoCliente(EstadoCliente.BLOQUEADO);
        return new Sucesso(String.format("Cliente %s bloqueado com sucesso!", cliente.getNomeCompleto()));
    }

    public Sucesso reativarCliente(Integer codCliente) throws SimbancException{
        Cliente cliente = this.clientes.get(codCliente);
        if (cliente.getEstadoCliente() != EstadoCliente.BLOQUEADO){
            String s = String.format("Cliente %s está %s e não pode ser desbloqueado",
                                     cliente.getNomeCompleto(),
                                     cliente.getEstadoCliente());
            throw new RegraNegocioException(s);
        }
        cliente.setEstadoCliente(EstadoCliente.ATIVO);
        return new Sucesso(String.format("Cliente %s desbloqueado com sucesso!", cliente.getNomeCompleto()));
    }

    public Sucesso cancelarCliente(Integer codCliente){
        Cliente cliente = this.clientes.get(codCliente);
        cliente.setEstadoCliente(EstadoCliente.CANCELADO);
        return new Sucesso(String.format("Cliente %s cancelado com sucesso!", cliente.getNomeCompleto()));
    }

    public List<Cliente> consultarPorNome(String nome){
        List<Cliente> aux = new ArrayList<Cliente>();
        for (Cliente c:this.clientes.values()){
            if (c.getNome().toUpperCase().contains(nome.toUpperCase()))
                aux.add(c);
        }
        return aux;
    }

    public Cliente consultarPorCPF(String cpf){
        for (Cliente c: this.clientes.values()){
            if (c instanceof ClienteFisico && ((ClienteFisico)c).getCpf().equals(cpf))
                return c;
        }
        return null;
    }
    
    public Cliente consultarPorCNPJ(String cnpj){
        for (Cliente c: this.clientes.values()){
            if (c instanceof ClienteJuridico && ((ClienteJuridico)c).getCnpj().equals(cnpj))
                return c;
        }
        return null;
    }

    public List<Cliente> listarClientes(){
        List<Cliente> clie = new ArrayList<Cliente>();
        clie.addAll(this.clientes.values());
        return clie;
    }

    public List<ClienteFisico> listarClientesFisicos(){
        List<ClienteFisico> clie = new ArrayList<ClienteFisico>();
        for (Cliente c:this.clientes.values()){
            if (c instanceof ClienteFisico)
                clie.add((ClienteFisico)c);
        }
        return clie;
    }
    
    public List<ClienteJuridico> listarClientesJuridicos(){
        List<ClienteJuridico> clie = new ArrayList<ClienteJuridico>();
        for (Cliente c:this.clientes.values()){
            if (c instanceof ClienteJuridico)
                clie.add((ClienteJuridico)c);
        }
        return clie;
    }
}
